package com.baofu.paycore.biz.paycore.handler.impl;

import com.baofu.account.service.facade.model.request.UnFreezeTransferReqDTO;
import com.baofu.paycore.biz.engine.result.CommandResult;
import com.baofu.paycore.biz.external.account.AccountService;
import com.baofu.paycore.biz.external.account.converter.AccountRequestConverter;
import com.baofu.paycore.biz.model.BackPayBO;
import com.baofu.paycore.biz.paycore.converter.BO2BOConverter;
import com.baofu.paycore.biz.paycore.handler.BaseHandler;
import com.baofu.paycore.common.enums.FundTypeEnum;
import com.baofu.paycore.common.enums.RedisKeyEnum;
import com.baofu.paycore.common.exception.PayCoreBizException;
import com.baofu.paycore.common.utils.RedisKeyUtil;
import com.baofu.paycore.dal.model.SubTransferDO;
import com.baofu.paycore.manager.cache.RedisManager;
import com.baofu.paycore.manager.model.RechargeBO;
import com.baofu.paycore.manager.model.ResponseBO;
import com.baofu.paycore.manager.model.TransferBO;
import com.baofu.paycore.manager.model.UnFreezeTransferRespBO;
import com.baofu.paycore.manager.storer.FreezeOrderRepository;
import com.baofu.paycore.manager.storer.TransferOrderRepository;
import com.baofu.paycore.service.facade.enums.PayCoreErrorCode;
import com.baofu.paycore.service.facade.enums.PayStatusEnums;
import com.google.common.collect.Maps;
import com.system.commons.exception.BizServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * <p>
 * </p>
 * User:ames wang  Date: 2017/6/28
 */
@Service
@Slf4j
public class UnfreezeTransferHandler extends BaseHandler<TransferBO, RechargeBO> {

    /**
     * 账务转账服务
     */
    @Autowired
    private AccountService accountService;

    /**
     * redis服务
     */
    @Autowired
    private RedisManager redisManager;

    /**
     * 持久服务
     */
    @Autowired
    private TransferOrderRepository transferOrderRepository;

    /**
     * 冻结持久服务
     */
    @Autowired
    private FreezeOrderRepository freezeOrderRepository;

    @Override
    public BackPayBO process(TransferBO transferBO) {
        log.debug("转账开始处理：{}", transferBO);
        doExecute(transferBO);
        log.debug("转账结果：{}", transferBO);
        return BO2BOConverter.transferBO2BackPayBO(transferBO);
    }

    @Override
    public TransferBO activeOrder(String orderId) {

        TransferBO transferBO = transferOrderRepository.load(orderId);
        if(transferBO == null){
            log.error("找不到订单:{}",orderId);
            throw new PayCoreBizException(PayCoreErrorCode.ORDER_IS_NOT_EXISTED);
        }
        return transferBO;
    }

    @Override
    public TransferBO queryOrderByPayNo(String payNo) {
        return activeOrder(payNo);
    }

    @Override
    protected void checkBeforeProcess(TransferBO order) {

    }

    /**
     * 生成指令
     *
     * @param order 单据
     */
    @Override
    protected void processOrders(TransferBO order) {

        //普通转账交易，才会判断是否收取手续费
        if (order.getBizChargeAmt() > 0) {
            Map<String, SubTransferDO> maps = this.getMap(order);
            //存在手续费,先执行解冻转账手续费功能
            this.unfreezeByFeeProcess(maps, order);
            processAfter(order, null);
            return;
        }

        //无手续费
        unfreezeTransfer(order);
        processAfter(order, null);
    }

    @Override
    protected void reStore(TransferBO order) {
       /* if(PayStatusEnums.SUCCESS.getCode().equals(order.getStatus())){
            transferOrderRepository.updateUnfreeze(order);
            return;
        }
        transferOrderRepository.update(order);*/
        Long dealAmt = 0l;
        for (SubTransferDO subTransferDO : order.getSubTransferDO()) {
            if (PayStatusEnums.SUCCESS.getCode().equals(subTransferDO.getStatus())) {
                dealAmt += subTransferDO.getPayAmount();
            }
        }
        if(dealAmt > 0){
            transferOrderRepository.updateUnfreeze(order, dealAmt);
            return;
        }
        transferOrderRepository.update(order);
    }

    @Override
    protected void processAfter(TransferBO order, Map<String, CommandResult> cmdResult) {
        List<SubTransferDO> subTransferDOs = order.getSubTransferDO();
        order.setStatus(PayStatusEnums.SUCCESS.getCode());
        for (SubTransferDO subTransferDO : subTransferDOs) {
            if (PayStatusEnums.FAIL.getCode().equals(subTransferDO.getStatus())) {
                order.setStatus(PayStatusEnums.FAIL.getCode());
                order.setErrorCode(subTransferDO.getErrorCode());
                order.setErrorMsg(subTransferDO.getErrorReason());
                break;
            }
            if (PayStatusEnums.INIT.getCode().equals(subTransferDO.getStatus())) {
                order.setStatus(PayStatusEnums.INIT.getCode());
                order.setErrorCode(subTransferDO.getErrorCode());
                order.setErrorMsg(subTransferDO.getErrorReason());
                break;
            }
        }
    }

    /**
     * 手续费解冻单处理
     *
     * @param maps       集合
     * @param transferBO 转账BO
     */
    private void unfreezeByFeeProcess(Map<String, SubTransferDO> maps, TransferBO transferBO) {
        SubTransferDO unfreezeByFee = maps.get(FundTypeEnum.FEE.getCode());
        String status = PayStatusEnums.SUCCESS.getCode();
        if (transferBO.getBizChargeAmt() > 0 && unfreezeByFee != null) {
            SubTransferDO subTransferDO = transferBO.getSubTransferDO(FundTypeEnum.FEE.getCode());
            subTransferDO.setFreezeCode(transferBO.getFreezeCode());
            unfreezeByFee.setFreezeCode(transferBO.getFreezeCode());
            this.unfreezeTransfer(subTransferDO, unfreezeByFee, transferBO);
            status = subTransferDO.getStatus();
        }
        //处理解冻转账单
        if (PayStatusEnums.SUCCESS.getCode().equals(status)) {
            this.unfreezeTransfer(transferBO);
        }
    }

    /**
     * 解冻转账
     *
     * @param subTransferDO 子转账单
     * @param unfreeze      解冻单
     * @param transferBO    转账
     */
    private void unfreezeTransfer(SubTransferDO subTransferDO, SubTransferDO unfreeze, TransferBO transferBO) {
        UnFreezeTransferReqDTO unFreezeTransfer = AccountRequestConverter.getUnfreezeTransfer(unfreeze, transferBO);
        UnFreezeTransferRespBO result =
                accountService.unFreezeTransfer(transferBO.getPayNo(), transferBO.getServiceCode(), unFreezeTransfer);

        this.unfreezeResult(subTransferDO, result);
    }

    /**
     * 解冻成功处理
     *
     * @param subTransferDO 转账单
     * @param result        解冻转账结果
     */
    private void unfreezeResult(SubTransferDO subTransferDO, UnFreezeTransferRespBO result) {
        subTransferDO.setStatus(result.getStatus());
        subTransferDO.setTransDate(result.getAccDate());
        subTransferDO.setTransReceiptNo(result.getTransferReceipt());
        subTransferDO.setUnfreezeReceipt(result.getUnfreezeReceipt());
        subTransferDO.setErrorCode(result.getErrorCode());
        subTransferDO.setErrorReason(result.getErrorMsg());
    }

    /**
     * 解冻转账处理
     *
     * @param transferBO 转账单
     */
    private void unfreezeTransfer(TransferBO transferBO) {
        SubTransferDO subTransferDO = transferBO.getSubTransferDO(FundTypeEnum.UNFREEZE_TRANSFER.getCode());
        if (subTransferDO == null) {
            log.error("子单为空:{}", transferBO.getPayNo());
            throw new BizServiceException(PayCoreErrorCode.TRANSFER_ORDER_ERROR);
        }
        subTransferDO.setFreezeCode(transferBO.getFreezeCode());
        this.unfreezeTransfer(subTransferDO, subTransferDO, transferBO);
    }

    /**
     * 转换Map集合
     *
     * @param transferBO    转账
     * @return              map集合
     */
    private Map<String,SubTransferDO> getMap(TransferBO transferBO){
        List<SubTransferDO> subTransferDOs = transferBO.getSubTransferDO();
        Map<String,SubTransferDO> map = Maps.newHashMap();
        for (SubTransferDO subTransferDO : subTransferDOs){
            map.put(subTransferDO.getFundType(), subTransferDO);
        }
        return map;
    }

    /**
     * 需重试接口 对内部资金单的重试（订单状态推进）
     *
     * @param transferBO  转账订单对象
     * @return ResponseBO
     * @throws RuntimeException 出现异常时表示重试没有成功（子类方法实现中不可捕获异常）
     */
    public ResponseBO dalInnerFundProc(TransferBO transferBO) throws RuntimeException {
        ResponseBO responseBO = null;
        //转账资金单
        List<SubTransferDO> subTransferDOs = transferBO.getSubTransferDO();
        for (SubTransferDO subTransfer : subTransferDOs){
            if (PayStatusEnums.SUCCESS.getCode().equals(subTransfer.getStatus())){
                log.debug("转账重试 资金单类型:{} 资金单号:{} 资金单状态:{}", subTransfer.getFundType(),
                        subTransfer.getFundDetailNo(), subTransfer.getStatus());
                continue;
            }
            if (PayStatusEnums.FAIL.getCode().equals(subTransfer.getStatus())){
                log.error("转账重试 资金单类型:{} 资金单号:{} 资金单状态:{}", subTransfer.getFundType(),
                        subTransfer.getFundDetailNo(), subTransfer.getStatus());
                break;
            }
            FundTypeEnum fundType = FundTypeEnum.explain(subTransfer.getFundType());
            if (null == fundType) continue;

            switch (fundType){
                case FEE:
                    responseBO = this.unfreezeTransfer(transferBO, subTransfer);
                    break;
                case UNFREEZE_TRANSFER:
                    responseBO = this.unfreezeTransfer(transferBO, subTransfer);
                    break;
                default:
                    log.error("暂不支持此业务：{}", fundType);
                    throw new PayCoreBizException(PayCoreErrorCode.NOT_IN_SERVICE);
            }
            if (null == responseBO){
                log.error("转账重试 资金单类型:{} 资金单号:{} 资金单状态:{}", subTransfer.getFundType(),
                        subTransfer.getFundDetailNo(), subTransfer.getStatus());
                break;
            }

            if (!validateContinue(responseBO.isRealFlag(), responseBO.getStatus())){
                log.error("重试 充值失败 请求服务类型:{} 资金单号:{} 资金单类型:{} 转账处理状态:{}", transferBO.getServiceCode(),
                        responseBO.getRequestNo(), subTransfer.getFundType(), responseBO.getStatus());
                break;
            }
        }
        processAfter(transferBO,null);
        reStore(transferBO);

        return responseBO;
    }

    /**
     * 重试解冻转账
     *
     * @param transferBO    转账单
     * @param subTransferDO 子转账单
     * @return              ResponseBO
     */
    private ResponseBO unfreezeTransfer(TransferBO transferBO, SubTransferDO subTransferDO){
        this.unfreezeTransfer(subTransferDO, subTransferDO, transferBO);
        return new ResponseBO(subTransferDO.getStatus(), subTransferDO.getErrorCode(),
                subTransferDO.getErrorReason(), subTransferDO.getTransDate(), subTransferDO.getTransReceiptNo(),
                subTransferDO.getFundDetailNo(), true);
    }

}
